package main.java.反射6;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.beanutils.BeanUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.*;

/**
 * @Auther:Liu
 * @Testname:Myjdbc
 * @Date:2025/3/14 9:29
 * <p>
 * Myjdbc使用德鲁伊连接池+反射封装的mysql操作类
 * Api：
 * insert (sql ,prem)           实现对mysql的增删改操作
 * findone(sql,cls,prem)        实现对mysql的查询（查询一条数据）
 * findall(sql,cls,prem)        实现对mysql的查询（查询多条数据）
 * findmap(sql,prem)            实现对mysql的查询（通过HashMap获取一条数据）
 * findmaps(sql,prem)           实现对mysql的查询（通过HashMap获取多条数据）
 * findshu(sql,prem)            实现对mysql的查询（通过数组获取一条数据）
 * findshus(sql,prem)           实现对mysql的查询（通过数组获取多条数据）
 */
public class Myjdbc {
//    private static String driverClass;
//    private static String url;
//    private static String username;
//    private static String password;
//
//    static {
//        try {
//            InputStream resourceAsStream = Myjdbc.class.getClassLoader().getResourceAsStream("反射6/protices.properties");
//            Properties properties = new Properties();
//            properties.load(resourceAsStream);
//            driverClass = properties.getProperty("driverClassName");
//            url = properties.getProperty("url");
//            username = properties.getProperty("username");
//            password = properties.getProperty("password");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }


    /**
     * 使用德鲁伊连接池连接对象
     *
     * @return Connection
     * @throws Exception
     */
    public static Connection conn() throws Exception {
        //法一
//        Properties properties = new Properties();
//        FileInputStream fileInputStream = new FileInputStream("src/反射6/protices.properties");
//        properties.load(fileInputStream);
//        //德鲁伊连接池
//        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//        Connection conn = dataSource.getConnection();
//        return conn;
        //法二
        Properties pro = new Properties();
        pro.load(Myjdbc.class.getClassLoader().getResourceAsStream("protices.properties"));
        DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
        Connection conn = dataSource.getConnection();
        return conn;
    }

    /**
     * 预编译对象
     *
     * @param sql  select * from ?    sql语句
     * @param prem 传递参数
     * @return PreparedStatement  预编译对象
     * @throws Exception
     */
    public static PreparedStatement pre(String sql, Object... prem) throws Exception {
        Connection conn = conn();
        PreparedStatement pre = conn.prepareStatement(sql);
        int Count = pre.getParameterMetaData().getParameterCount();
        for (int i = 0; i < Count; i++) {
            pre.setObject(i + 1, prem[i]);
        }
        return pre;
    }

    /**
     * 对mysql进行增删改
     *
     * @param sql  sql语句
     * @param prem 传递参数
     * @return int
     * @throws Exception
     */
    public static int insert(String sql, Object... prem) throws Exception {
        int i = pre(sql, prem).executeUpdate();
        close(null, null,null);
        return i;
    }

    /**
     * 对mysql进行查询,获取一条数据
     *
     * @param sql  sql语句
     * @param cls  反射对象
     * @param prem 传递参数
     * @param <T>  泛型
     * @return <T> T   泛型对象
     * @throws Exception
     */
    public static <T> T findone(String sql, Class<T> cls, Object... prem) throws Exception {
        T t = null;
        PreparedStatement pre = pre(sql, prem);
        ResultSet resultSet = pre.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        t = cls.getConstructor().newInstance();
        int Count = metaData.getColumnCount();
        resultSet.next();
        for (int i = 1; i <= Count; i++) {
            BeanUtils.setProperty(t, metaData.getColumnName(i), resultSet.getObject(i));
        }
        close(resultSet, pre,null);
        return t;
    }

    /**
     * 对mysql进行查询,获取多条数据
     *
     * @param sql  sql语句
     * @param cls  反射对象
     * @param prem 传递参数
     * @param <T>  泛型
     * @return <T> List<T>  泛型列表
     * @throws Exception
     */
    public static <T> List<T> findall(String sql, Class<T> cls, Object... prem) throws Exception {
        ArrayList<T> ts = new ArrayList<>();//创建数组
        PreparedStatement pre = pre(sql, prem);//连接加预编译
        ResultSet resultSet = pre.executeQuery();//获取结果集
        ResultSetMetaData metaData = resultSet.getMetaData();//获取元数据
        int Count = metaData.getColumnCount();//获取列数
        while (resultSet.next()) {//循环打印数据
            T t = cls.getConstructor().newInstance();//创建对象
            for (int i = 1; i <= Count; i++) {
                BeanUtils.setProperty(t, metaData.getColumnName(i), resultSet.getObject(i));//映射对象
            }
            ts.add(t);//添加元素对象
        }
//        close(sql,prem);
        return ts;//返回列表
    }

    /**
     * 通过HashMap,即键值对的形式查找并返回mysql中一条数据
     *
     * @param sql  sql语句
     * @param prem 传递参数
     * @return HashMap<String, Object>  哈希Map
     * @throws Exception
     */
    public static HashMap<String, Object> findmap(String sql, Object... prem) throws Exception {
        PreparedStatement pre = pre(sql, prem);
        ResultSet resultSet = pre.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int Count = metaData.getColumnCount();
        HashMap<String, Object> objectObjectHashMap = new HashMap<>();
        resultSet.next();
        for (int i = 0; i < Count; i++) {
            objectObjectHashMap.put(metaData.getColumnName(i + 1), resultSet.getObject(i + 1));
        }
        close(resultSet, pre,null);
        return objectObjectHashMap;
    }

    /**
     * 通过HashMap,即键值对的形式查找并返回mysql中多条数据
     *
     * @param sql  sql语句
     * @param prem 传递参数
     * @return ArrayList<Map>  Map集合
     * @throws Exception
     */
    public static ArrayList<Map> findmaps(String sql, Object... prem) throws Exception {
        PreparedStatement pre = pre(sql, prem);
        ResultSet resultSet = pre.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int Count = metaData.getColumnCount();
        ArrayList<Map> maps = new ArrayList<>();
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        while (resultSet.next()) {
            for (int i = 0; i < Count; i++) {
                objectObjectHashMap.put(metaData.getColumnName(i + 1), resultSet.getObject(i + 1));
            }
            maps.add(objectObjectHashMap);
        }
        close(resultSet, pre,null);
        return maps;
    }

    /**
     * 通过数组的形式,查找并返回mysql中一条数据
     *
     * @param sql  sql语句
     * @param prem 传递参数
     * @return Object[] Object类数组
     * @throws Exception
     */
    public static Object[] findshu(String sql, Object... prem) throws Exception {
        PreparedStatement pre = pre(sql, prem);
        ResultSet resultSet = pre.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int Count = metaData.getColumnCount();
        Object[] objects = new Object[Count];
        resultSet.next();
        for (int i = 0; i < Count; i++) {
            objects[i] = resultSet.getObject(i + 1);
        }
        close(resultSet, pre,null);
        return objects;
    }

    /**
     * 通过集合中包含数组的形式,查找并返回mysql中多条数据
     *
     * @param sql  sql语句
     * @param prem 传递参数
     * @return ArrayList<Object [ ]>  数组形式的集合
     * @throws Exception
     */
    public static ArrayList<Object[]> findshus(String sql, Object... prem) throws Exception {
        PreparedStatement pre = pre(sql, prem);
        ResultSet resultSet = pre.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int Count = metaData.getColumnCount();
        ArrayList<Object[]> objects = new ArrayList<>(Count);
        while (resultSet.next()) {
            Object[] maps = new Object[Count];
            for (int i = 0; i < Count; i++) {
                maps[i] = resultSet.getObject(i + 1);
            }
            objects.add(maps);
        }
        close(resultSet, pre,null);
        return objects;
    }

    /**
     * 关闭资源
     *
     * @param resultSet 结果集
     * @param pre       预编译对象
     * @throws Exception
     */
    public static void close(ResultSet resultSet, PreparedStatement pre,Connection conn) throws Exception {
        if (conn != null) {
            conn.close();
        }
        if (pre != null) {
            pre.close();
        }
        if (resultSet != null) {
            resultSet.close();
        }
    }

}